package parser;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;

import javax.crypto.EncryptedPrivateKeyInfo;

import main.Main;
import parser.domain.Factory;
import parser.domain.Grammar;
import parser.domain.LL1Table;
import parser.domain.NonTerminalSymbol;
import parser.domain.Symbol;
import parser.domain.TerminalSymbol;

public class LL1Parser {
	private final Symbol DOLLAR = new TerminalSymbol("$");
	private final String file = "g1.txt";
	private LL1Table table;

	public LL1Parser() {
		Grammar gr;
		try {
			gr = Factory.loadGrammarFromFile(file);

			table = new LL1Table(gr);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public List<String> parse(List<String> input) {
		Stack<Symbol> working = new Stack<>();
		List<String> productionStrings = new ArrayList<>();

		working.push(DOLLAR);
		working.push(new NonTerminalSymbol("S")); // TODO
		input.add(DOLLAR.toString());

		String inputTop = input.get(0);
		Symbol workingTop;
		List<Symbol> prodRhs;
		while (!working.peek().equals(DOLLAR)
				|| !input.get(0).equals(DOLLAR.getSymbol())) {
			// && !input.get(0).equals(DOLLAR.getSymbol())) {
			workingTop = working.pop();
			inputTop = input.get(0);

			System.out.println(workingTop + " " + inputTop);

			//if the working stack is empty but there still is input -> error
			if (workingTop.equals(DOLLAR) && input.size() > 1) {
				// WOW. Such error. Much panic!!!
				System.out.println("MUCH ERRROR! WOW!");
				return null;
			}

			if (workingTop.getSymbol().equals(inputTop)
					&& workingTop instanceof TerminalSymbol) {
				// pop
				input.remove(0);
				continue;
			}
			if (workingTop.getSymbol().equals(Main.EPSILON)) {
				continue;
			}

			if (!inputTop.equals(DOLLAR.getSymbol())) {
				prodRhs = table.get(workingTop, new TerminalSymbol(inputTop));
			} else {
				prodRhs = table.get(workingTop,
						new TerminalSymbol(Main.EPSILON));
			}
			// push
			if (prodRhs == null || prodRhs.size() == 0) {
				// WOW. Such error. Much panic!!!
				System.out.println("MUCH ERRROR! WOW!");
				return null;
			} else {
				// push
				List<Symbol> tList = new ArrayList<>(prodRhs);
				Collections.reverse(tList);
				for (Symbol s : tList) {
					working.push(s);
				}
				productionStrings.add(workingTop.toString() + "->" + prodRhs);
			}
		}
		System.out.println("SUCCESS!");
		return productionStrings;
	}

	public void push(List<Symbol> s) {
		for (Symbol symbol : s) {

		}
	}
}
